#include "TransformActor.h"
#include "Scene.h"

namespace egg{

    TransformActor::TransformActor(){
        mScaled=false;
    }

    void TransformActor::onUpdateTransform(){
        if(mTransformDirty){
            mTransformDirty=false;
            mLocal2ParentMatrix=glm::toMat4(mOrientation);
            mLocal2ParentMatrix[3]=vec4(mPosition,1.0);
            mLocal2WorldMatrix=mParent->getLocal2WorldMatrix()*mLocal2ParentMatrix;
        }
    }

    void TransformActor::translate(const vec3& _dist,TransformSpace _ts){
        vec3 relDist;
        switch(_ts){
        case TS_LOCAL:
            relDist=mOrientation*_dist;
            break;
        case TS_PARENT:
            relDist=_dist;
            break;
        case TS_WORLD:
            relDist=mOrientation*(glm::inverse(mat3(mParent->getLocal2ParentMatrix()))*_dist);
            break;
        }
        setPosition(mPosition+relDist,TS_PARENT);
    }

    void TransformActor::setPosition(const vec3& _pos,TransformSpace _ts){
        switch(_ts){
        case TS_LOCAL:
            mPosition=vec3(mParent->getLocal2WorldMatrix()*vec4(_pos,1.0));
            break;
        case TS_PARENT:
            mPosition=_pos;
            break;
        case TS_WORLD:
            vec4 localPos=glm::inverse(mParent->getLocal2ParentMatrix())*vec4(_pos,1.0);
            mPosition=vec3(mParent->getLocal2ParentMatrix()*localPos);
            break;
        }
        notifyTransformDirty();
    }

    void TransformActor::rotate(float _deg,const vec3& _axis,TransformSpace _ts){
        vec3 rotAxis;
        switch(_ts){
        case TS_LOCAL:
            rotAxis=mOrientation*_axis;
            break;
        case TS_PARENT:
            rotAxis=_axis;
            break;
        case TS_WORLD:
            rotAxis=mat3(glm::inverse(mParent->getLocal2ParentMatrix()))*_axis;
            rotAxis=mOrientation*_axis;
            break;
        }
        rotAxis=glm::normalize(rotAxis);
        mOrientation=glm::angleAxis(_deg,rotAxis)*mOrientation;
        mOrientation=glm::normalize(mOrientation);

        notifyBoundingDirty();
        notifyTransformDirty();
    }

    vec4 TransformActor::getWorldPosition(){
        return mLocal2WorldMatrix[3];
    }

    const mat4& TransformActor::getLocal2WorldMatrix(){
        return mLocal2WorldMatrix;
    }

    const mat4& TransformActor::getLocal2ParentMatrix(){
        return mLocal2ParentMatrix;
    }

}